/**************************************************************************************************
**                                                                                               **
**  文件名称:  fsm_resetrec.c                                                                    **
**  版权所有:  CopyRight @ Xiamen Yaxon NetWork CO.LTD. 2017                                     **
**  文件描述:  复位管理模块                                                                      **
**  ===========================================================================================  **
**  创建信息:  | 2017-4-24 | LEON | 创建本模块                                                   **
**  ===========================================================================================  **
**  修改信息:  单击此处添加....                                                                  **
**************************************************************************************************/
#include "fsm_include.h"
#include "fsm_resetrec.h"

/*************************************************************************************************/
/*                           模块静态变量                                                        */
/*************************************************************************************************/
static RESET_REC_T s_rst_rec;

/**************************************************************************************************
**  函数名称:  PrintResetInfo
**  功能描述:  打印复位信息
**  输入参数:  all: 是否需要打印详情
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void PrintResetInfo(BOOLEAN all)
{
    #if EN_DEBUG > 0
    
    INT8U   i, maxno;
    
    Debug_SysPrint("SysRestart Rec: Total[%.4d]. Ext[%.4d]. Int[%.4d]\r\n", s_rst_rec.total, s_rst_rec.extrn, s_rst_rec.intal);
    
    if (all == FALSE) {                                                /* 不需要打印详情 */
        return;
    }
    
    maxno = (s_rst_rec.total > MAX_REC_EXT) ? MAX_REC_EXT : s_rst_rec.total;
    
    for (i = 0; i < maxno; i++) {
        
        Debug_SysPrint("%d. ", i);
        
        Debug_SysPrint("20%.2d-%.2d-%.2d %.2d:%.2d:%.2d. ", s_rst_rec.rsrec[i].time.date.year,   s_rst_rec.rsrec[i].time.date.month, 
                                                            s_rst_rec.rsrec[i].time.date.day,    s_rst_rec.rsrec[i].time.time.hour, 
                                                            s_rst_rec.rsrec[i].time.time.minute, s_rst_rec.rsrec[i].time.time.second);
        Debug_SysPrint("%15s/%.5d. ", s_rst_rec.rsrec[i].file, s_rst_rec.rsrec[i].line);
        
        switch (s_rst_rec.rsrec[i].type)
        {
            case SYSRST_EXTRN:
                Debug_SysPrint("EXT.\r\n");
                break;
            
            case SYSRST_INTAL:
                Debug_SysPrint("INT.\r\n");
                break;
            
            default:
                Debug_SysPrint("XXX.\r\n");
                break;
        }
    }
    
    #endif
}

/**************************************************************************************************
**  函数名称:  FillResetData
**  功能描述:  记录复位信息
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void FillResetData(RESET_TYPE_E type, char *file, INT32U line)
{
    INT8U maxlen, wkday;
    
    memmove(&s_rst_rec.rsrec[1], &s_rst_rec.rsrec[0], sizeof(RST_REC_T) * (MAX_REC_EXT - 1));
    
    DAL_RTC_GetSystime(&s_rst_rec.rsrec[0].time, &wkday);
    
    maxlen = sizeof(s_rst_rec.rsrec[0].file) - 1;
    YX_MEMCPY(s_rst_rec.rsrec[0].file, file, maxlen);
    
    s_rst_rec.rsrec[0].file[maxlen] = '\0';
    s_rst_rec.rsrec[0].line = line;
    
    switch (type)
    {
        case SYSRST_EXTRN:
            s_rst_rec.extrn++;
            s_rst_rec.rsrec[0].type = SYSRST_EXTRN;
            break;
            
        case SYSRST_INTAL:
            s_rst_rec.intal++;
            s_rst_rec.rsrec[0].type = SYSRST_INTAL;
            break;
            
        default:
            SYS_ASSERT(0, RETURN_VOID);
    }
}

/**************************************************************************************************
**  函数名称:  RecordResetInfo
**  功能描述:  复位前的回调函数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
static void RecordResetInfo(RESET_TYPE_E event, char *file, INT32U line)
{
    FillResetData(event, file, line);
    PP_WriteItem(PP_RESETREC, &s_rst_rec, FALSE);                              /* 这里无需用TRUE，因为后面会立即存储 */
    PP_WriteAllItems();
    
    #if DEBUG_COMM > 0
    Debug_SysPrint("===================================\r\n");
    Debug_SysPrint("Assert File: %s\r\n", file);
    Debug_SysPrint("Assert Line: %.5d\r\n", line);
    if (event == SYSRST_EXTRN) {
        Debug_SysPrint("Assert Type: Extern\r\n");
    } else if (event == SYSRST_INTAL) {
        Debug_SysPrint("Assert Type: Inside\r\n");
    } else {
        Debug_SysPrint("Assert Type: Unkown\r\n");
    }
    Debug_SysPrint("===================================\r\n");
    #endif
}

/**************************************************************************************************
**  函数名称:  ResetRec_Init
**  功能描述:  复位记录模块初始化
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void ResetRec_Init(void)
{
    INT32U rstcnt;
    
    SYS_ASSERT(BSP_RegistResetInform(RecordResetInfo) == TRUE, RETURN_VOID);
    
    if (PP_ReadItem(PP_RESETREC, &s_rst_rec) == FALSE) {                       /* 如果读取参数失败，则全部初始化 */
        YX_MEMSET((INT8U *)&s_rst_rec, 0, sizeof(s_rst_rec));
    } else {
        rstcnt = s_rst_rec.extrn + s_rst_rec.intal;                            /* 统计复位总次数 */
        
        if (rstcnt == s_rst_rec.total + 1) {                                   /* 说明本次复位是出错复位 */
            s_rst_rec.total++;
        } else if (rstcnt == s_rst_rec.total) {                                /* 说明本次复位是外部复位 */
            s_rst_rec.total++;
            FillResetData(SYSRST_EXTRN, "None_CodeFile.c", 0);
        } else {                                                               /* 说明统计和异常，重新计算 */
            s_rst_rec.total = rstcnt;
        }
    }
    
    PP_WriteItem(PP_RESETREC, &s_rst_rec, TRUE);
    
    PrintResetInfo(FALSE);                                                     /* 打印简单的复位统计信息 */
}

/**************************************************************************************************
**  函数名称:  PrintSysResetRec
**  功能描述:  打印出系统复位信息
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void PrintSysResetRec(void)
{
    PrintResetInfo(TRUE);                                                      /* 打印详细的复位全部信息 */
}

/**************************************************************************************************
**  函数名称:  ClearAllResetRec
**  功能描述:  清除所有的复位记录信息
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
void ClearAllResetRec(void)
{
    YX_MEMSET((INT8U *)&s_rst_rec, 0, sizeof(s_rst_rec));
}

/**************************************************************************************************
**  函数名称:  GetIntResetCnt
**  功能描述:  获取内部复位总次数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT32U GetIntResetCnt(void)
{
    return s_rst_rec.intal;
}

/**************************************************************************************************
**  函数名称:  GetExtResetCnt
**  功能描述:  获取外部复位总次数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT32U GetExtResetCnt(void)
{
    return s_rst_rec.extrn;
}

/**************************************************************************************************
**  函数名称:  GetTotalResetCnt
**  功能描述:  获取系统复位总次数
**  输入参数:  无
**  输出参数:  无
**  返回参数:  无
**************************************************************************************************/
INT32U GetTotalResetCnt(void)
{
    return s_rst_rec.total;
}



